﻿using System;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Reflection;
using SalesSys.Comm.DAL;
using SalesSys.Comm.Utility;

namespace SalesSys.BLL
{
    public class RepositoryFactory
    {
        public RepositoryFactory() :this(new DefUnitContext())
        { 
        }

        /// <summary>
        /// 创建一个新的仓储工厂，并手动设置其工作单元
        /// </summary>
        /// <param name="unitContext"></param>
        public RepositoryFactory(IUnitContext unitContext)
        {
            UnitContext = unitContext;
        }
        public static Assembly[] ExtLoadAssemblys = null;

        static readonly CompositionContainer Container = null;

        static RepositoryFactory()
        {
                AggregateCatalog cat = new AggregateCatalog();

              var  path =AppRunInfo.GetBinDir();
                var dirCatalog = new DirectoryCatalog(path,"SalesSys.*.dll");

                cat.Catalogs.Add(dirCatalog);
                
                if (ExtLoadAssemblys != null && ExtLoadAssemblys.Length > 0)
                {
                    foreach (var item in ExtLoadAssemblys)
                    {
                        AssemblyCatalog extAss = new AssemblyCatalog(item);
                        cat.Catalogs.Add(extAss);
                    }
                }
                Container = new CompositionContainer(cat, CompositionOptions.IsThreadSafe);
        }

        public IUnitContext UnitContext
        {
            get;
            private set;
        }

        public T GetRepository<T>(string contractName = null) where T : IRepository
        {
            T val;
            //MefCont();
            if (contractName == null)
            {
                val = Container.GetExportedValue<T>();
            }
            else val = Container.GetExportedValue<T>(contractName);
            val.UnitContext = UnitContext;
            return val;
        }
        /// <summary>
        /// 创建一个没有设置context的仓储实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="contractName"></param>
        /// <returns></returns>
        [Obsolete("如果要自定义context请使用有构造函数的RepositoryFactory")]
        public T GetRepositoryNoContext<T>(string contractName = null) where T : IRepository
        {
            T val;
            //MefCont();
            if (contractName == null)
            {
                val = Container.GetExportedValue<T>();
            }
            else val = Container.GetExportedValue<T>(contractName);
           // val.UnitContext = unitContext;
            return val;
        }

        

        #region static
        /// <summary>
        /// 工厂类在http中存储的名称
        /// </summary>
        public static readonly string RepositoryFactoryAtHttpContextName = "_nowRepositoryFactory";
       

        /// <summary>
        /// 默认工厂创建办法，除测试外，此属性不应手动设置
        /// </summary>
        public static Func<RepositoryFactory> FactoryCreateMode;

        //todo 用户信息传递需重实现
        //public static readonly string ContextUserInfoSign = UserHelper.ContextUserInfoSign;
        //public static readonly string ContextAdminInfoSign = AdminUserHelper.ContextAdminInfoSign;

        /// <summary>
        /// 获取默认工作单元的仓储实现
        /// 注意：此仓储是一个默认实现的上下文工作单元，不能完整实现工作单元事物，只能保证同一dbContext下事物，
        /// 如需完整事物单元，请使用：TranScopeUnitContext
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="contractName"></param>
        /// <returns></returns>
        public static T GetRepositoryByFactoryUnit<T>(string contractName = null) where T : IRepository
        {
            return FactoryCreateMode().GetRepository<T>(contractName);
        }
        #endregion
    }


    
}
